/* $Id: pjsua_reg.c 5373 2016-06-30 08:23:08Z ming $ */
/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#include <pjsua-lib/pjsua.h>
#include <pjsua-lib/pjsua_internal.h>


#define THIS_FILE   "pjsua_reg.c"


//const pjsip_method pjsip_register_method =
//{
//    (pjsip_method_e) PJSIP_REGISTER_METHOD,
//    { "REGISTER", 8 }
//};


/* Proto */
static pj_bool_t reg_on_rx_request(pjsip_rx_data *rdata);


/* The module instance. */
static pjsip_module mod_pjsua_reg = 
{
    NULL, NULL,				/* prev, next.		*/
    { "mod-pjsua-reg", 13 },		/* Name.		*/
    -1,					/* Id			*/
    PJSIP_MOD_PRIORITY_APPLICATION,	/* Priority	        */
    NULL,				/* load()		*/
    NULL,				/* start()		*/
    NULL,				/* stop()		*/
    NULL,				/* unload()		*/
    &reg_on_rx_request,			/* on_rx_request()	*/
    NULL,				/* on_rx_response()	*/
    NULL,				/* on_tx_request.	*/
    NULL,				/* on_tx_response()	*/
    NULL,				/* on_tsx_state()	*/

};


/**
 * Private: check if we can accept the REGISTER.
 */
pj_bool_t pjsua_reg_accept_pager(pjsip_rx_data *rdata,
    pjsip_accept_hdr **p_accept_hdr)
{
    /* Ticket #693: allow incoming REGISTER without body */
    PJ_UNUSED_ARG(rdata);
    PJ_UNUSED_ARG(p_accept_hdr);

    return PJ_TRUE;
}

/**
 * Private: process pager message.
 *	    This may trigger pjsua_ui_on_pager() or pjsua_ui_on_typing().
 */
void pjsua_reg_process_pager(int call_id, const pj_str_t *from,
    const pj_str_t *to, pjsip_rx_data *rdata)
{
    if (pjsua_var.ua_cfg.cb.on_reg_state3) {
        (*pjsua_var.ua_cfg.cb.on_reg_state3)(from, to, rdata);
    }
}


/*
 * Handler to receive incoming REGISTER
 */
static pj_bool_t reg_on_rx_request(pjsip_rx_data *rdata)
{
    pj_str_t from, to;
    pjsip_accept_hdr *accept_hdr;
    pjsip_msg *msg;

    msg = rdata->msg_info.msg;

    PJ_LOG(5,(THIS_FILE,""));

    /* Only want to handle REGISTER requests. */
    if (pjsip_method_cmp(&msg->line.req.method, &pjsip_register_method) != 0) {
        return PJ_FALSE;
    }


    /* Should not have any transaction attached to rdata. */
    PJ_ASSERT_RETURN(pjsip_rdata_get_tsx(rdata)==NULL, PJ_FALSE);

    /* Should not have any dialog attached to rdata. */
    PJ_ASSERT_RETURN(pjsip_rdata_get_dlg(rdata)==NULL, PJ_FALSE);

    /* Check if we can accept the message. */
    if (!pjsua_reg_accept_pager(rdata, &accept_hdr)) {
        pjsip_hdr hdr_list;

        pj_list_init(&hdr_list);
        pj_list_push_back(&hdr_list, accept_hdr);

        pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 
            PJSIP_SC_NOT_ACCEPTABLE_HERE, NULL, 
            &hdr_list, NULL);
        return PJ_TRUE;
    }

    /* Respond with 200 first, so that remote doesn't retransmit in case
     * the UI takes too long to process the message. 
     */
    //pjsip_endpt_respond( pjsua_var.endpt, NULL, rdata, 200, NULL,
     //   NULL, NULL, NULL);

    /* For the source URI, we use Contact header if present, since
     * Contact header contains the port number information. If this is
     * not available, then use From header.
     */
    from.ptr = (char*)pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
    from.slen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, 
        rdata->msg_info.from->uri,
        from.ptr, PJSIP_MAX_URL_SIZE);

    if (from.slen < 1)
        from = pj_str("<--URI is too long-->");

    /* Build the To text. */
    to.ptr = (char*) pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
    to.slen = pjsip_uri_print( PJSIP_URI_IN_FROMTO_HDR, 
        rdata->msg_info.to->uri,
        to.ptr, PJSIP_MAX_URL_SIZE);
    if (to.slen < 1)
        to = pj_str("<--URI is too long-->");

    /* Process pager. */
    pjsua_reg_process_pager(-1, &from, &to, rdata);

    /* Done. */
    return PJ_TRUE;
}


/*
 * Init pjsua REGISTER module.
 */
pj_status_t pjsua_reg_init(void)
{
    const pj_str_t msg_tag = { "REGISTER", 8 };
    pj_status_t status;

    /* Register module */
    status = pjsip_endpt_register_module(pjsua_var.endpt, &mod_pjsua_reg);
    if (status != PJ_SUCCESS)
        return status;

    /* Register support for MESSAGE method. */
    pjsip_endpt_add_capability( pjsua_var.endpt, &mod_pjsua_reg, PJSIP_H_ALLOW,
        NULL, 1, &msg_tag);

    return PJ_SUCCESS;
}

